'''
多条语句 tip:
1.在调用表达式的一侧 应尽量重置当前最新的tn编号为 返回结果所在的寄存器下一个,便于将高编号寄存器回收。
'''

'''
语义新增的数据结构:
0.我们假定当前语义分析并不使用真正的寄存器，我们使用t0 t1 t2....tn 这样的临时结果"寄存器"
  为了处理的简便 retDict中新增一个当前最新可用临时寄存器编号变量 tn, 每一步骤出现变量时 需要为变量新建一个临时的tn来保存值 
1.retDict中新增 我们定义的名为asmCodes的列表结构 来保存每一步骤生成的中间四元式:
[
  {"row":行数(作为语句的偏移地址 用来指示跳转语句的目的地),"op":操作指令,"arg1":源参数,"arg2":目的参数,"res":产生新值应存到哪个结果当中},
  ....
  {同上构造的字典}
]
2.retDict中新增 我们定义一个返回本步骤值的结果: res
3.我们应定义一张符号表symbTable：
当且仅当某变量声明时，为其创建存储空间并记录到符号表中。
symbTable是一个列表，每一项对应一个符号的信息(规定变量地址从1000开始编址):
[
{"id":符号变量名,"type":变量类型,"size":变量大小,"addr":变量地址},
......
{同上构造字典}
]
'''



'''
  函数表
    |-testExprBox(tokens,tn)                  检测并提取Expr元素返回结果字典
    |-testBlock(tokens)                       检测并提取Blcok元素返回结果字典
    |-testDecls(tokens,table)                 检测并提取Decls元素返回结果字典
    |-testDecl(tokens,table)                  检测并提取Decl元素返回结果字典
      |-testType(tokens)                      检测并提取type元素返回结果字典
      |-testNameList(tokens,idType,table)     检测并提取NameList元素返回结果字典
        |-testName(token)                     检测并提取Name元素返回结果字典
    |-testStms(tokens,tn,table)               检测并提取Stms元素返回结果字典
    |-testStm(tokens,tn,table)                检测并提取Stm元素返回结果字典
      |-testAssign(tokens,tn)                 检测并提取Stm_assign元素返回结果字典
      |-testWhile(tokens,tn,table)            检测并提取Stm_while元素返回结果字典
      |-testIfElse(tokens,tn,table)           检测并提取Stm_if(或Stm_if_else)元素返回结果字典
        |-testIf(tokens,tn,table)             检测并提取if元素返回结果字典
        |-testElse(tokens,tn,table)           检测并提取else元素返回结果字典
    |-testRel(tokens,tn)                      检测并提取Rel元素返回结果字典
      |-testROp(tokens)                       检测并提取Rop元素返回结果字典
    |-extractBlock(tokens)                    检测并提取{}内的token序列返回结果字典
    |-extractBreaket(tokens)                  检测并提取()内的token序列返回结果字典
    |-getCodeUnit(tokens)                     从tokens中获得一个语法单元
    |-getTokens(tokens,id,tid)                安全提取tokens[id][tid]的内容 越界返回空而非报错
    |-updateAsmCodes(oldCodes,newCodes)       更新行号 将子节点的四元式链入父节点的四元式列表中
    |-getTypeJump(ROP,isNega)                 根据ROP来获得对应选择的条件跳转四元式符号
    |-addSymb2Table(table,id,IdType,size)     将新的符号加入符号表
  '''



import Expr #引入算术表达式判定模块

#testExprBox() 检测并提取Expr元素内容 对引入的表达式检测做了二次封装
#tokens  词法单位序列
# 返回一个结果字典 
def testExprBox(tokens,tn):
  retDict=Expr.testExpr(tokens,tn)
  #不是tx 直接复位tn
  if retDict["res"][0]!="t":
    retDict["tn"]=tn
  #若是tx 则考虑将tn复位到最小占用编号的下一个
  else:
    usedTn=retDict["res"][1:]
    retDict["tn"]=int(usedTn)+1
  return retDict


#testBlock() 检测并提取Block元素
#tokens  词法单位序列
# 返回一个结果字典 
def testBlock(tokens,tn,table):
  # print("Block",tokens)
  need=[]
  needTree={"root":None}
  #1.检测Decls
  retDict1=testDecls(tokens,table)
  if not retDict1["status"]:
    return {"status":0}
  else:
    need.append([1,"{"])
    need.extend(retDict1["need"])
    needTree["leafA"]=retDict1["needTree"]
    table=retDict1["table"]
  #2.检测Stms
  retDict2=testStms(retDict1["new"],tn,table)
  if not retDict2["status"]:
    return {"status":0}
  else:
    need.extend(retDict2["need"])
    need.append([1,"}"])
    needTree["leafB"]=retDict2["needTree"]
    needTree["root"]=["Block",need]
    return {"status":1,"need":need,"new":retDict2["new"],"needTree":needTree,"tn":retDict2["tn"],"asmCodes":retDict2["asmCodes"],"table":retDict2["table"]}


#testDecls() 检测并提取Decls元素
#tokens  词法单位序列
# 返回一个结果字典 
def testDecls(tokens,table):
  # print("Decls",tokens)
  need=[]
  new=[]
  needTree={"root":None}
  #1.获取一个语法单位
  retDict1=getCodeUnit(tokens)
  #1.1 检测是否存在语法单位错误
  if not retDict1["status"]:
    return {"status":0}
  #1.2 检测是否为空
  elif retDict1["status"]==3:
    return {"status":1,"need":need,"new":[],"needTree":needTree,"table":table}
  #1.3 检测是否为代码块(若是代码块则将解析前的原样传回)  
  elif retDict1["status"]==2:
    return {"status":1,"need":need,"new":tokens,"needTree":needTree,"table":table}
  #1.4 检测为单行语句则传入Decl
  elif retDict1["status"]==1:
    
    #1.4.1 检测Decl
    retDict2=testDecl(retDict1["need"],table)
    if not retDict2["status"]:
      return {"status":1,"need":need,"new":tokens,"needTree":needTree,"table":table}
    need.extend(retDict2["need"])
    needTree["leafA"]=retDict2["needTree"]
    table=retDict2["table"]
    #1.4.2 检测Decls
    retDict3=testDecls(retDict1["new"],table)
    if not retDict3["status"]:
      return {"status":0}
    else:
      need.extend(retDict3["need"])
      new.extend(retDict3["new"])
      needTree["leafB"]=retDict3["needTree"]
      needTree["root"]=["Decls",need]
      return {"status":1,"need":need,"new":new,"needTree":needTree,"table":retDict3["table"]}

#testDecl() 检测并提取Decl元素
#tokens  词法单位序列
# 返回一个结果字典 
def testDecl(tokens,table):
  # print("Decl",tokens)
  needTree={"root":None}
  need=[]
  #1.检测 type是否合法
  retDict1=testType(tokens)
  if not retDict1["status"]:
    return {"status":0}
  else:
    need.extend(retDict1["need"])
    needTree["leafA"]=retDict1["needTree"]
  #2.检测名字清单
  retDict2=testNameList(retDict1["new"],retDict1["typeres"],table)
  if not retDict2["status"]:
    return {"status":0}
  else:
    need.extend(retDict2["need"])
    need.append([1,";"])
    # print("[Decl]:"+need)
    needTree["leafB"]=retDict2["needTree"]
    needTree["root"]=["Decl",need]
    return {"status":1,"need":need,"needTree":needTree,"table":retDict2["table"]}


#testType()检测并提取Decl中的Type元素
#tokens  词法单位序列
# 返回一个结果字典 
def testType(tokens):
  # print("Type",tokens)
  #读取前三个字符必须是int 且int后必须空一格
  if getTokens(tokens, 0, 1)=="int" and len(tokens)>1:
    return {"status":1,"need":[tokens[0]],"new":tokens[1:],"needTree":["Type",[ tokens[0] ] ],"typeres":getTokens(tokens, 0, 1)}  
  else:
    return {"status":0}

#testNameList() 检测并提取NameList元素
#tokens  词法单位序列
# 返回一个结果字典 
def testNameList(tokens,idType,table):
  # print("NameList",tokens)
  typeSizeDict={"int":4}

  needTree={"root":None}
  need=[]
  name=[]
  flagNameLists=0
  if len(tokens)>2 and tokens[1][1]==",":
    flagNameLists=1
    name=tokens[0]
  elif len(tokens)==1:
    name=tokens[0]
  else:
    raise Exception("error:声明语句错误 在"+getTokens(tokens, 0, 1)+"处存在不合法的变量清单!")
    return {"status":0}

  #1.存在,(存在多个name)
  if flagNameLists:
    #1.2检测一个Name
    retDict1=testName(name)
    if not retDict1["status"]:
      raise Exception("error:"+name+"并非合法标识符!")
      return {"status":0}
    table=addSymb2Table(table,name[1],idType,typeSizeDict[idType])
    need.extend(retDict1["need"])
    need.append([1,","])
    needTree["leafA"]=retDict1["needTree"]
    #1.3 将剩下的字段送入检测NameList
    retDict2=testNameList(tokens[2:],idType,table)
    if not retDict2["status"]:
      return {"status":0}
    need.extend(retDict2["need"])
    needTree["leafB"]=retDict2["needTree"]
    needTree["root"]=["NameList",need]
    return {"status":1,"need":need,"needTree":needTree,"table":retDict2["table"]}
  #2.不存在, 只有一个name
  else:
    #2.1 检测一个Name
    retDict3=testName(name)
    if not retDict3["status"]:
      raise Exception("error:"+name+"并非合法标识符!")
      return {"status":0}
    else:
      need.extend(retDict3["need"])
      needTree["leafA"]=retDict3["needTree"]
      needTree["root"]=["NameList",need]
      table=addSymb2Table(table,name[1],idType,typeSizeDict[idType])
      
      return {"status":1,"need":need,"needTree":needTree,"table":table}


#testName() 检测并提取Name元素 实际用作自定义标识符的检测
#token 一个词法单位
#返回一个结果字典
def testName(token):
  # print("Name",token)
  if token[0]==3:
    return{"status":1,"need":[token],"needTree":["Id",[token]]}
  #不属于上述任意情况的 统统报错
  return{"status":0}



#testStms() 检测并提取Stms元素
#tokens  词法单位序列
# 返回一个结果字典 
def testStms(tokens,tn,table):
  # print("Stms",tokens)
  asmCodes=[]
  need=[]
  new=[]
  needTree={"root":None}
  #1.获取一个语法单位(检错 检空)
  retDict1=getCodeUnit(tokens)
  #1.1 检测是否存在语法单位错误
  if not retDict1["status"]:
    return {"status":0}
  #1.2 检测是否为空
  elif retDict1["status"]==3:
    return {"status":1,"need":need,"new":[],"needTree":needTree,"asmCodes":[],"tn":tn,"table":table}
  
  #2.检测Stm
  retDict2=testStm(tokens,tn,table)
  if not retDict2["status"]:
    return {"status":0}
  need.extend(retDict2["need"])
  needTree["leafA"]=retDict2["needTree"]
  asmCodes=updateAsmCodes(asmCodes,retDict2["asmCodes"])
  tn=retDict2["tn"]
  table=retDict2["table"]
  #3.检测Stms
  retDict3=testStms(retDict2["new"],tn,table)
  if not retDict3["status"]:
    return {"status":0}
  else:
    need.extend(retDict3["need"])
    new.extend(retDict3["new"])
    needTree["leafB"]=retDict3["needTree"]
    needTree["root"]=["Stms",need]
    asmCodes=updateAsmCodes(asmCodes,retDict3["asmCodes"])
    tn=retDict3["tn"]
    return {"status":1,"need":need,"new":new,"needTree":needTree,"asmCodes":asmCodes,"tn":tn,"table":retDict3["table"]} 


#testStm() 检测并提取Stm元素
#tokens  词法单位序列
# 返回一个结果字典 
def testStm(tokens,tn,table):
  asmCodes=[]
  # print("Stm",tokens)
  #1.获取一个语法单位
  retDict1=getCodeUnit(tokens)
  #1.1 检测是否存在语法单位错误
  if not retDict1["status"]:
    return {"status":0}
  #1.2 检测是否为空(empty) 存疑
  elif retDict1["status"]==3:
    raise Exception("error:"+getTokens(tokens,0, 1)+"处出现非法空语句!")
  # 1.3 检测是否为纯代码块(即 { 前方不含if/while/else字段的) 
  elif retDict1["status"]==2 and len(retDict1["before"])==0:
    retDict5=testBlock(retDict1["need"],tn,table)
    if not retDict5["status"]:
      return {"status":0}
    return {"status":1,"need":retDict5["need"],"new":retDict1["new"],"needTree":retDict5["needTree"],"tn":retDict5["tn"],"asmCodes":retDict5["asmCodes"],"table":retDict5["table"]}

  #1.4 检测为单行语句则转入(必定单行语句 赋值语句 检测)
  elif retDict1["status"]==1:  
    #1.4.1 检测是否为赋值
    retDict2=testAssign(retDict1["need"],tn)
    if retDict2["status"]:
      # print("[Stm]:"+retDict2["need"])  
      tn=retDict2["tn"]
      asmCodes=updateAsmCodes(asmCodes,retDict2["asmCodes"])
      return {"status":1,"need":retDict2["need"],"new":retDict1["new"],"needTree":retDict2["needTree"],"asmCodes":asmCodes,"tn":tn,"table":table}
  #1.5 其余情况下(含代码块且{前有东西的 单行语句但不是赋值) 进行三类模糊语句的检测    
  #1.5.1 while语句检测
  retDict3=testWhile(tokens,tn,table)
  if retDict3["status"]:
    # print("[Stm]:"+retDict3["need"]) 
    tn=retDict3["tn"]
    asmCodes=updateAsmCodes(asmCodes,retDict3["asmCodes"])
    return {"status":1,"need":retDict3["need"],"new":retDict3["new"],"needTree":retDict3["needTree"],"asmCodes":asmCodes,"tn":tn,"table":retDict3["table"]}
  #1.5.2 检测是否为if-else
  retDict4=testIfElse(tokens,tn,table)
  if retDict4["status"]:
    tn=retDict4["tn"]
    asmCodes=updateAsmCodes(asmCodes,retDict4["asmCodes"])
    # print("[Stm]:"+retDict4["need"]) 
    return {"status":1,"need":retDict4["need"],"new":retDict4["new"],"needTree":retDict4["needTree"],"asmCodes":asmCodes,"tn":tn,"table":retDict4["table"]}
  raise Exception("error:"+getTokens(tokens,0, 1)+"处出现非法语句!")


#testAssign() 检测并提取 stm_assign 元素
#tokens  词法单位序列
# 返回一个结果字典 
def testAssign(tokens,tn):
  # print("Assign",tokens)
  asmCodes=[]
  need=[]
  compents=[] #保存赋值号左右两侧的元素
  needTree={"root":None}
  #1.检测 是否有赋值号
  if len(tokens)>2 and tokens[1][1]=="=":
    compents=[tokens[0],tokens[2:]]
  else:
    return {"status":0}
  
  needTree["leafB"]=["AOp",[tokens[1]]]
  need.append(tokens[1])
  #2.检测左侧是否为id
  retDict1=testName(compents[0])
  if not retDict1["status"]:
    raise Exception("error:赋值语句的左式 "+getTokens(compents,0, 1)+"并非合法标识符!") 
  else:
    needTree["leafA"]=retDict1["needTree"]
    need.extend(retDict1["need"])
    need.reverse()
    print("compents[0]",compents[0])
  idres=getTokens(compents,0, 1)

  #3.检测右侧是否为表达式
  retDict2=testExprBox(compents[1],tn)
  if not retDict2["status"]:
    raise Exception("error:赋值语句的右式 以"+getTokens(compents[1],0, 1)+"开头的表达式错误!") 
  else:
    need.extend(retDict2["need"])
    need.append([1,";"])
    needTree["leafC"]=retDict2["needTree"]
    needTree["root"]=["Stm_Assign",need]
  expres=retDict2["res"]
  tn=retDict2["tn"]
  asmCodes=updateAsmCodes(asmCodes,retDict2["asmCodes"])
  asmCodes=updateAsmCodes(asmCodes,[{"row":1,"op":":=","arg1":str(expres),"arg2":idres,"res":idres}])
  return {"status":1,"need":need,"needTree":needTree,"tn":tn,"asmCodes":asmCodes}




#testWhile() 检测并提取 while (Rel) Stm 元素
#tokens  词法单位序列 tn为当前最新临时变量下标 
#table为符号表
# 返回一个结果字典 
def testWhile(tokens,tn,table):
  # print("While",tokens)
  asmCodes=[]
  need=[]
  needTree={"root":None}
  #读取一个语法单位
  retDict1=getCodeUnit(tokens)
  #由testSTM可知,这个语法单位绝对不可能出现空或者错误
  #1.头部分析
  #1.1根据语句构型来分割while头部 while(REL)
    #1.1是一条语句
  if retDict1["status"]==1:
    head_tokens=retDict1["need"]
    #1.2是一个语句块  
  elif retDict1["status"]==2:
    head_tokens=retDict1["before"]
  #1.2头部检测
  #1.2.1 检测开头是否存在while
  if getTokens(head_tokens,0,1)!="while" and len(head_tokens)>1:
    return {"status":0}
  #1.2.2 获取括号中的条件表达式
  retDict2=extractBreaket(head_tokens[1:])
  if not retDict2["status"]:
    return {"status":0}
  #1.2.3 解析条件表达式
  retDict3=testRel(retDict2["need"],tn)
  if not retDict3["status"]:
    return {"status":0}
  needTree["leafA"]=["Head",[head_tokens[0]]]
  needTree["leafB"]=retDict3["needTree"]
  need.append(head_tokens[0])
  need.append([1,"("])
  need.extend(retDict3["need"])
  need.append([1,")"])
  #生成了xx xx xx cmp
  asmCodes=updateAsmCodes(asmCodes,retDict3["asmCodes"])
  #回跳的地址
  addrBack=asmCodes[-1]["row"]-len(retDict3["asmCodes"])+1
  tn=retDict3["tn"]
  
  #2.躯干STM分析
  #2.1 提取STM
  ## 若为块则取出块解析内容补上{}构成Blcok形作为STM,反之单条语句 则取出while(REL)后方的内容 同时补上;构成单条语句 
  stm_tokens=[]
  if retDict1["status"]==2:
    stm_tokens.append([1,"{"])
    stm_tokens.extend(retDict1["need"])
    stm_tokens.append([1,"}"])
  else:
    stm_tokens.extend(retDict2["new"])
    stm_tokens.append([1,";"])
  
  #2.2 STM检测
  retDict4=testStm(stm_tokens,tn,table)
  if not retDict4["status"]:
    return {"status":0}
  else:
    need.extend(retDict4["need"])
    needTree["leafC"]=retDict4["needTree"]
    needTree["root"]=["Stm_while",need]
    #结束循环后要走的位置
    addrOut=len(retDict4["asmCodes"])+2
    # 生成cmp下的跳转
    asmCodes.append({"row":asmCodes[-1]["row"]+1,"op":getTypeJump(retDict3["opres"],1),"arg1":asmCodes[-1]["row"]+1+addrOut,"arg2":" ","res":" "})
    asmCodes=updateAsmCodes(asmCodes,retDict4["asmCodes"])
    nextrow=asmCodes[-1]["row"]+1
    asmCodes.append({"row":nextrow,"op":"j","arg1":addrBack,"arg2":" ","res":" "})
    tn=retDict4["tn"]
    return {"status":1,"need":need,"new":retDict1["new"],"needTree":needTree,"asmCodes":asmCodes,"tn":tn,"table":retDict4["table"]}



#testIfEsle() 检测并提取if (Rel) Stm 元素 或 if (Rel) Stm else Stm 元素
#tokens  词法单位序列
# 返回一个结果字典 
def testIfElse(tokens,tn,table):
  # print("IF-ELSE",tokens)
  asmCodes=[]
  need=[]
  needTree={}
  #1.检测if
  retDict1=testIf(tokens,tn,table)
  if not retDict1["status"]:
    return {"status":0}
  need.extend(retDict1["need"])
  needTree=retDict1["needTree"]
  tn=retDict1["tn"]
  asmCodes=updateAsmCodes(asmCodes,retDict1["asmCodes"])
  table=retDict1["table"]
  # needTree["root"]=need
  #2.继续向后读一个语法单位 并判断其是否符合else判断
  retDict2=getCodeUnit(retDict1["new"])
    #若语法单位为错误或空 则返回if判定结果
  if retDict2["status"]==0 or retDict2["status"]==3:
    needTree["root"]=["Stm_if",need]
    return {"status":1,"need":need,"new":retDict1["new"],"needTree":needTree,"tn":tn,"asmCodes":asmCodes,"table":table}
  #3.反之则检测else
  retDict3=testElse(retDict1["new"],tn,table)
  if not retDict3["status"]:
    needTree["root"]=["Stm_if",need]
    return {"status":1,"need":need,"new":retDict1["new"],"needTree":needTree,"tn":retDict1["tn"],"asmCodes":asmCodes,"tabler":etDict1["table"]}
  else:
    need.extend(retDict3["need"])
    needTree["root"]=["Stm_if_else",need]
    needTree["leafD"]=retDict3["needTree"]["leafA"]
    needTree["leafE"]=retDict3["needTree"]["leafB"]
    tn=retDict3["tn"]
    asmCodes=updateAsmCodes(asmCodes,retDict3["asmCodes"])
    return {"status":1,"need":need,"new":retDict3["new"],"needTree":needTree,"asmCodes":asmCodes,"tn":tn,"table":retDict3["table"]}


#testIf() 检测并提取 if (Rel) Stm 元素
#tokens  词法单位序列
# 返回一个结果字典 
def testIf(tokens,tn,table):
  asmCodes=[]
  need=[]
  needTree={"root":None}
  #读取一个语法单位
  retDict1=getCodeUnit(tokens)
  #print("【if_retDict1】"+str(retDict1))
  #由testIfElse可知,这个语法单位绝对不可能出现空或者错误
  #1.头部分析
  #1.1根据语句构型来分割if头部 if(REL)
    #1.1是一条语句
  if retDict1["status"]==1:
    head_tokens=retDict1["need"]
    #1.2是一个语句块  
  elif retDict1["status"]==2:
    head_tokens=retDict1["before"]
  #1.2头部检测
  #1.2.1 检测开头是否存在if
  if getTokens(head_tokens,0,1)!="if" and len(head_tokens)>1:
    return {"status":0}
  #1.2.2 获取括号中的条件表达式
  retDict2=extractBreaket(head_tokens[1:])
  if not retDict2["status"]:
    return {"status":0}
  #1.2.3 解析条件表达式
  retDict3=testRel(retDict2["need"],tn)
  if not retDict3["status"]:
    return {"status":0}
  needTree["leafA"]=["Head",[head_tokens[0]]]
  needTree["leafB"]=retDict3["needTree"]
  need.append(head_tokens[0])
  need.append([1,"("])
  need.extend(retDict3["need"])
  need.append([1,")"])
  #生成cmp以及求表达式的语句
  tn=retDict3["tn"]
  asmCodes=updateAsmCodes(asmCodes,retDict3["asmCodes"])
  nextrow=asmCodes[-1]["row"]+1
  #2.躯干STM分析
  #2.1 提取STM
  ## 若为块则取出块解析内容补上{}构成Blcok形作为STM,反之单条语句 则取出if(REL)后方的内容 同时补上;构成单条语句 
  stm_tokens=[]
  if retDict1["status"]==2:
    stm_tokens.append([1,"{"])
    stm_tokens.extend(retDict1["need"])
    stm_tokens.append([1,"}"])
  else:
    stm_tokens.extend(retDict2["new"])
    stm_tokens.append([1,";"])
  
  #2.2 STM检测
  retDict4=testStm(stm_tokens,tn,table)
  if not retDict4["status"]:
    return {"status":0}
  else:
    need.extend(retDict4["need"])
    needTree["leafC"]=retDict4["needTree"]
    # needTree["root"]=need
    tn=retDict4["tn"]
    addrOut=len(retDict4["asmCodes"])+1
    # 生成cmp下的跳转
    asmCodes.append({"row":nextrow,"op":getTypeJump(retDict3["opres"],1),"arg1":addrOut+nextrow+1,"arg2":" ","res":" "})
    asmCodes=updateAsmCodes(asmCodes,retDict4["asmCodes"])
    return {"status":1,"need":need,"new":retDict1["new"],"needTree":needTree,"tn":tn,"asmCodes":asmCodes,"table":retDict4["table"]}


#testElse() 检测并提取 else Stm 元素
#tokens  词法单位序列
# 返回一个结果字典 
def testElse(tokens,tn,table):
  need=[]
  needTree={}
  #读取一个语法单位
  retDict1=getCodeUnit(tokens)
  #由testIfElse可知,这个语法单位绝对不可能出现空或者错误
  #1.头部分析
  #1.1根据语句构型来分割else头部 else
    #1.1是一条语句
  if retDict1["status"]==1:
    head_tokens=retDict1["need"]
    #1.2是一个语句块  
  elif retDict1["status"]==2:
    head_tokens=retDict1["before"]
  #1.2头部检测
  #1.2.1 检测开头是否存在else
  if getTokens(head_tokens,0,1)!="else" and len(head_tokens)>1:
    return {"status":0}

  need.append(head_tokens[0])
  needTree["leafA"]=["Head",[head_tokens[0]]]
  #2.躯干STM分析
  #2.1 提取STM
  ## 若为块则取出块解析内容补上{}构成Blcok形作为STM,反之单条语句 则取出else后方的内容 同时补上;构成单条语句 


  stm_tokens=[]
  if retDict1["status"]==2:
    stm_tokens.append([1,"{"])
    stm_tokens.extend(retDict1["need"])
    stm_tokens.append([1,"}"])
  else:
    stm_tokens.extend(head_tokens[1:])
    stm_tokens.append([1,";"])


  #2.2 STM检测
  retDict2=testStm(stm_tokens,tn,table)
  if not retDict2["status"]:
    return {"status":0}
  else:
    need.extend(retDict2["need"])
    needTree["leafB"]=retDict2["needTree"]
    tn=retDict2["tn"]
    addrElseOut=len(retDict2["asmCodes"])+1
    asmCodes=updateAsmCodes([{"row":1,"op":"j","arg1":addrElseOut+1,"arg2":" ","res":" "}],retDict2["asmCodes"])
    return {"status":1,"need":need,"new":retDict1["new"],"needTree":needTree,"tn":tn,"asmCodes":asmCodes,"table":retDict2["table"]}

#testRel() 检测并提取Rel元素
#tokens  词法单位序列
# 返回一个结果字典 
def testRel(tokens,tn):
  opres=""
  asmCodes=[]
  #print("Rel",tokens)
  needTree={"root":None}
  need=[]
  #1.检测运算符
  retDict1=testROp(tokens)
  if not retDict1["status"]:
    raise Exception("error:"+getTokens(tokens,0, 1)+"与"+getTokens(tokens, len(tokens)-1, 1)+"之间未找到关系运算符") 
    return {"status":0}
  else:
    opres=retDict1["res"]
    needTree["leafB"]=retDict1["needTree"]
    need.extend(retDict1["need"])
  compents=retDict1["new"]
 
  #2.左侧表达式检测
  retDict2=testExprBox(compents[0],tn)
  if not retDict2["status"]:
    raise Exception("error:关系表达式的左式 以"+getTokens(compents[0],0, 1)+"开头的表达式错误!") 
    return {"status":0}
  else:
    needTree["leafA"]=retDict2["needTree"]
    need.extend(retDict2["need"])
    need.reverse()
  leftres=retDict2["res"]
  asmCodes=updateAsmCodes(asmCodes,retDict2["asmCodes"])
  tn=retDict2["tn"]

  #3.右侧表达式检测
  retDict3=testExprBox(compents[1],tn)
  if not retDict3["status"]:
    raise Exception("error:关系表达式的右式 以"+getTokens(compents[1],0, 1)+"开头的表达式错误!") 
    return {"status":0}
  else:
    need.extend(retDict3["need"])
    needTree["leafC"]=retDict3["needTree"]
    needTree["root"]=["Rel",need]
    rightres=retDict3["res"]
    asmCodes=updateAsmCodes(asmCodes,retDict3["asmCodes"])
    asmCodes=updateAsmCodes(asmCodes,[{"row":1,"op":"cmp","arg1":leftres,"arg2":rightres,"res":" "}])
    tn=retDict3["tn"]
    return {"status":1,"need":need,"needTree":needTree,"tn":tn,"asmCodes":asmCodes,"opres":opres}


#testROp()检测并提取RoP元素
#tokens  词法单位序列
# 返回一个结果字典 
def testROp(tokens):
  # print("ROp",tokens)
  ROp=[">=","<=","==","!=",">","<"]
  res=""
  for op in ROp:
    for index,token in enumerate(tokens):
      if op == token[1]:
        res=op
        compents=[tokens[:index],tokens[index+1:]]
        return {"status":1,"need":[token],"new":compents,"needTree":["ROp",[token]],"res":res}
  return {"status":0}


#extractBlock()去除{}后获取其中并返回剩余代码
#同时也会检测{}是否匹配
#返回结果字典
def extractBlock(tokens):
  count=0
  if getTokens(tokens,0,1)!='{':
    raise Exception("error:在"+getTokens(tokens, 0, 1)+"处缺少{")
    return {"status":0,"need":None,"new":None}
  for index,token in enumerate(tokens):
    if token[1] =="{":
      count+=1
    elif token[1]=="}":
      count-=1
      if count==0:
        return {"status":1,"need":tokens[1:index],"new":tokens[index+1:]}
      #说明出现了孤单的情况
      if count<0:
        raise Exception("error:"+getTokens(tokens, index-1, 1)+"之后的}缺少与之匹配的{")
        return {"status":0,"need":None,"new":None}
  raise Exception("error:"+getTokens(tokens, len(tokens)-1, 1)+"之后缺少配对的}")
  return {"status":0,"need":None,"new":None}


#extractBreaket() 提取一层括号中的内容
#expr 表达式字符串
# 返回一个结果字典
#  {
#     "status":结果状态(0找到|1没找到),
#     "need":返回括号内的元素(元素字符串|None),
#     "new":返回)后的tokens(表达式字符串|None),
#   }
def extractBreaket(tokens):
  # print("Breat",tokens)
  count=0
  #1.检测首个是否为(
  if getTokens(tokens,0,1) != '(':
    raise Exception("error:在"+getTokens(tokens, 0, 1)+"处缺少(")
    return {"status":0,"need":None,"new":None}
  for index,token in enumerate(tokens):
    if token[1] =="(":
      count+=1
    elif token[1] ==")":
      count-=1
      if count==0:
        return {"status":1,"need":tokens[1:index],"new":tokens[index+1:]}
      if count<0:
        raise Exception("error:"+getTokens(tokens, index-1, 1)+"后的)缺少与之匹配的(")
        return {"status":0,"need":None,"new":None}
  raise Exception("error:"+getTokens(tokens, len(tokens)-1, 1)+"之后缺少配对的)")
  return {"status":0,"need":None,"new":None}


#继续向前获得一个语法单元
#我们认为语法单元分为两种
#{}包含的block块语句 以及;分割的行语句 line
#返回结果字典
#  {
#     "status":(0不存在|1是单行|2是block|3代码正常结束),
#     "before":前方文本(为block时存在|None)
#     "need":当前解析出的语法单位内容 (block则是里面的内容 单行则是去掉一个;的) 
#     "new":后方文本(该单位后方的文本|None)
#   }
def getCodeUnit(tokens):
  for index,token in enumerate(tokens):
    #1.碰到block
    if token[1] =="{":
      retDict1=extractBlock(tokens[index:])
      #1.1 block异常
      if not retDict1["status"]:
        return {"status":0}
      else:
      #1.2 block正常 返回block中前方代码 block中的代码 以及后续的代码  
        return {"status":2,"before":tokens[:index],"need":retDict1["need"],"new":retDict1["new"]}
    #2.碰到单行语句
      #2.1
    if token[1]==";":
      return {"status":1,"before":None,"need":tokens[:index],"new":tokens[index+1:]}
  
  #3.没有触发block或者语句结束
  #3.1 若此时的tokens序列空了 则正常结束 若不正常结束则报错
  if len(tokens)==0:
    return {"status":3}
  #3.2 若包含其他字符内容 此时结束不正常
  else:
    raise Exception("error:"+getTokens(tokens, len(tokens)-1, 1)+"之后缺少语句结束标志")
    return {"status":0}



#获取tokens中编号为id的token(当token不足时会返还""或-1)
#获取token中对应tid的数据(0类型说明|1内容)
def getTokens(tokens,id,tid):
  if len(tokens):
    return tokens[id][tid]
  else:
    return "" if tid==1 else -1 



#对newCodes更新行号并链入oldCodes中
def updateAsmCodes(oldCodes,newCodes):
  if len(oldCodes)==0:
    return newCodes
  old_startIndex=oldCodes[-1]["row"]
  for line in newCodes:
    if line["op"][0]=="j":    #跳转语句要更新行号
      line["arg1"]=line["arg1"]+old_startIndex
    line["row"]=line["row"]+old_startIndex
    oldCodes.append(line)
  return oldCodes

#根据给定的ROP来判断 跳转类型, isNega为1表示取反,其他表示不取
def getTypeJump(ROP,isNega):
  ROPs=[">=","<=","==","!=",">","<"]
  #j=["jae","jbe","je","jne","ja","jb"]    
  # NJump=["jb","ja","jne","je","jbe","jae"]
  j=["j>=","j<=","j=","j!=","j>","j<"]
  NJump=["j<","j>","j!=","j=","j<=","j>="]
  if isNega==1:
    return NJump[ROPs.index(ROP)]
  else:
    return j[ROPs.index(ROP)]



#向符号表中新增一个变量
#table当前符号表 id变量名 type类型  size变量大小 
def addSymb2Table(table,id,IdType,size):
  if len(table)==0: 
    return [{'id':id,'type':IdType,'size':size,'addr':1000}]
  for idinfo in table:
    if id == idinfo["id"]:
      return table 
  table.append({'id':id,'type':IdType,'size':size,'addr':table[-1]['addr']+table[-1]['size'] })
  return table 